package org.zy.server;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import org.zy.core.Message;

import java.util.UUID;

public class VisitorHandler extends SimpleChannelInboundHandler<ByteBuf> {

    /**
     * 访客连接
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("访客：建立连接");

        Channel channel = ctx.channel();
        // 不自动读取
        channel.config().setOption(ChannelOption.AUTO_READ, false);

        String visitorId = UUID.randomUUID().toString();

        // 绑定访客
        channel.attr(ChannelManager.VISITOR_ID).set(visitorId);
        ChannelManager.VISITOR_CHANNEL_MAP.put(visitorId, channel);

        // 代理服务器发起与客户端连接
        Message msg = new Message(Message.TYPE_CONNECT, visitorId.getBytes());
        ChannelManager.CLIENT_MAIN_CHANNEL.writeAndFlush(msg);

        super.channelActive(ctx);
    }

    /**
     * 访客数据传输
     *
     * @param ctx
     * @param byteBuf
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) {
        System.out.println("访客：发送数据");

        String visitorId = ctx.channel().attr(ChannelManager.VISITOR_ID).get();
        if (null == visitorId || visitorId.length() == 0) {
            return;
        }

        // 读取访客数据
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        Message msg = new Message(Message.TYPE_TRANSFER, bytes);

        // 代理服务器发送数据到客户端
        Channel clientChannel = ChannelManager.CLIENT_CHANNEL_MAP.get(visitorId);
        clientChannel.writeAndFlush(msg);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("访客：关闭连接");

        String visitorId = ctx.channel().attr(ChannelManager.VISITOR_ID).get();
        if (null == visitorId || visitorId.length() == 0) {
            super.channelInactive(ctx);
            return;
        }

        Channel clientChannel = ChannelManager.CLIENT_CHANNEL_MAP.get(visitorId);
        if (null != clientChannel && clientChannel.isActive()) {
            clientChannel.config().setOption(ChannelOption.AUTO_READ, true);
            Message msg = new Message(Message.TYPE_DISCONNECT, visitorId.getBytes());
            clientChannel.writeAndFlush(msg);
        }

        ChannelManager.removeVisitor(visitorId);
        super.channelInactive(ctx);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        Channel visitorChannel = ctx.channel();

        String visitorId = ctx.channel().attr(ChannelManager.VISITOR_ID).get();
        if (null == visitorId || visitorId.length() == 0) {
            super.channelWritabilityChanged(ctx);
            return;
        }

        Channel clientChannel = ChannelManager.CLIENT_CHANNEL_MAP.get(visitorId);
        if (null != clientChannel) {
            clientChannel.config().setOption(ChannelOption.AUTO_READ, visitorChannel.isWritable());
        }

        super.channelWritabilityChanged(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}